package com.lfz.demo.controller;

import com.lfz.demo.entity.Logs;
import com.lfz.demo.service.LogsService;
import com.lfz.demo.service.UserService;
import com.lfz.demo.utils.RedisUtil;
import com.lfz.demo.vo.DataView;
import com.lfz.demo.vo.LogsVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/logs")
public class LogsController {
    private static final Logger logger = LoggerFactory.getLogger(LogsController.class);
    private static final String CACHE_PREFIX = "logs:";
    private static final int CACHE_EXPIRE_MINUTES = 30;

    @Autowired
    private LogsService logsService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 查询全部信息（带Redis缓存）
     */
    @GetMapping("/selectAll")
    public DataView selectAll(LogsVo logsVo) {
        String cacheKey = generateCacheKey(logsVo);

        try {
            // 尝试从缓存获取
            DataView cachedData = (DataView) redisUtil.get(cacheKey);
            if (cachedData != null) {
//                logger.info("命中缓存: {}", cacheKey);
                return cachedData;
            }
        } catch (Exception e) {
            logger.error("Redis访问异常，降级到数据库查询", e);
        }

        try {
            // 数据库查询
            DataView dataView = executeDatabaseQuery(logsVo);

            // 异步缓存结果
            cacheResultAsync(cacheKey, dataView);

            return dataView;
        } catch (Exception e) {
            logger.error("日志查询异常", e);
            return new DataView(0L, Collections.emptyList());
        }
    }

    /**
     * 删除单条日志（带缓存清理）
     */
    @PostMapping("/delete/{id}")
    public DataView delete(@PathVariable Integer id) {
        DataView response = new DataView();
        try {
            // 删除前获取日志信息用于清理缓存
            Optional<Logs> log = Optional.ofNullable(logsService.getById(id));

            if (logsService.removeById(id)) {
                // 清理相关缓存
                clearRelatedCaches();
                response.setCode(200);
                response.setMsg("删除成功");
            } else {
                response.setCode(404);
                response.setMsg("日志不存在");
            }
        } catch (Exception e) {
            logger.error("删除日志失败 ID: {}", id, e);
            response.setCode(500);
            response.setMsg("删除失败: " + e.getMessage());
        }
        return response;
    }

    /**
     * 批量删除日志（带缓存清理）
     */
    @PostMapping("/delete/batch")
    public DataView batchDelete(@RequestBody List<Integer> ids) {
        DataView response = new DataView();
        try {
            if (ids == null || ids.isEmpty()) {
                response.setCode(400);
                response.setMsg("参数错误");
                return response;
            }

            if (logsService.removeByIds(ids)) {
                // 清理相关缓存
                clearRelatedCaches();
                response.setCode(200);
                response.setMsg("成功删除 " + ids.size() + " 条日志");
            } else {
                response.setCode(500);
                response.setMsg("部分日志删除失败");
            }
        } catch (Exception e) {
            logger.error("批量删除失败", e);
            response.setCode(500);
            response.setMsg("批量删除失败: " + e.getMessage());
        }
        return response;
    }

    // 以下是私有工具方法

    /**
     * 生成唯一缓存键
     */
    private String generateCacheKey(LogsVo vo) {
        return String.format("%sselectAll:page-%d_limit-%d_menu-%s_operator-%s_type-%s_start-%s_end-%s",
                CACHE_PREFIX,
                vo.getPage(),
                vo.getLimit(),
                StringUtils.hasText(vo.getOperateMenu()) ? vo.getOperateMenu() : "all",
                StringUtils.hasText(vo.getOperator()) ? vo.getOperator() : "all",
                StringUtils.hasText(vo.getOperateType()) ? vo.getOperateType() : "all",
                vo.getStartTime() != null ? vo.getStartTime().getTime() : 0,
                vo.getEndTime() != null ? vo.getEndTime().getTime() : 0);
    }

    /**
     * 执行数据库查询
     */
    private DataView executeDatabaseQuery(LogsVo vo) {
        Pageable pageable = PageRequest.of(vo.getPage() - 1, vo.getLimit());

        Specification<Logs> spec = buildSpecification(vo);
        Page<Logs> page = logsService.findByPage(spec, pageable);

        return new DataView(page.getTotalElements(), page.getContent());
    }

    /**
     * 构建查询条件
     */
    private Specification<Logs> buildSpecification(LogsVo vo) {
        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (StringUtils.hasText(vo.getOperateMenu())) {
                predicates.add(cb.like(root.get("operateMenu"), "%" + vo.getOperateMenu() + "%"));
            }

            if (StringUtils.hasText(vo.getOperator())) {
                predicates.add(cb.like(root.get("operator"), "%" + vo.getOperator() + "%"));
            }

            if (StringUtils.hasText(vo.getOperateType())) {
                predicates.add(cb.like(root.get("operateType"), "%" + vo.getOperateType() + "%"));
            }

            if (vo.getStartTime() != null && vo.getEndTime() != null) {
                predicates.add(cb.between(root.get("operateTime"), vo.getStartTime(), vo.getEndTime()));
            } else if (vo.getStartTime() != null) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("operateTime"), vo.getStartTime()));
            } else if (vo.getEndTime() != null) {
                predicates.add(cb.lessThanOrEqualTo(root.get("operateTime"), vo.getEndTime()));
            }

            query.orderBy(cb.desc(root.get("operateTime")));
            return cb.and(predicates.toArray(new Predicate[0]));
        };
    }

    /**
     * 异步缓存结果
     */
    private void cacheResultAsync(String key, DataView data) {
        new Thread(() -> {
            try {
                redisUtil.set(key, data, CACHE_EXPIRE_MINUTES);
//                logger.info("成功缓存数据 Key: {}", key);
            } catch (Exception e) {
                logger.error("异步缓存设置失败 Key: {}", key, e);
            }
        }).start();
    }

    /**
     * 清理相关缓存
     */
    private void clearRelatedCaches() {
        try {
            redisUtil.deletePattern(CACHE_PREFIX + "*");
//            logger.info("成功清理日志相关缓存");
        } catch (Exception e) {
            logger.error("缓存清理失败", e);
        }
    }
}